/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
#include <filesystem>
#include <functional>
#include <string>
#include <vector>

#include <mc/common.h>
#include <mc/dict.h>
#include "../../../libraries/mctp/mctp.h"
#include "../../../libraries/ncsi/ncsi_huawei.h"
#include "../../../libraries/ncsi/ncsi_protocol.h"
#include "../../../libraries/ncsi_over_mctp/ncsi_over_mctp_huawei.h"

namespace mc {
class dict;
}

namespace dev {
mc::dict get_ncsi_command_ctx(uint8_t package_id, uint8_t channel_id, uint8_t packet_type,
                              uint8_t expect_rsp_packet_type);
mc::dict get_oem_command_ctx(uint8_t package_id, uint8_t channel_id);
uint32_t convert_speed_mbps(uint32_t speed_mbps);
bool convert_full_duplex(uint8_t full_duplex);
uint8_t convert_link_status(uint8_t link_status);
bool check_respense_data(oem_huawei_public_rsp_t* rsp, uint8_t oem_sub_command_id);
std::string get_link_width_str(uint8_t link_width);
std::string get_link_speed_str(uint8_t link_speed);
std::string get_medium_type_str(uint8_t medium_type);
std::string get_connector_type_str(uint8_t connector_type);
std::string get_identifier_str(uint8_t identifier);
float covert_micro_to_milli(uint16_t value);
void set_mctp_request_handler(std::function<bool(const mc::dict&, const std::vector<uint8_t>&,
                                                 std::string&)> handler);
} // namespace dev

namespace {

constexpr uint16_t host_to_be16(uint16_t value) {
    return static_cast<uint16_t>(((value & 0x00FFU) << 8U) | ((value & 0xFF00U) >> 8U));
}

static_assert(OEM_HUAWEI_MAC_ADDR_RSP_LEN == 64, "unexpected mac addr response length");

constexpr uint32_t host_to_be32(uint32_t value) {
    return ((value & 0x000000FFU) << 24U) | ((value & 0x0000FF00U) << 8U) |
           ((value & 0x00FF0000U) >> 8U) | ((value & 0xFF000000U) >> 24U);
}

class ncsi_over_mctp_huawei_test : public ::testing::Test {
protected:
    ncsi_over_mctp_huawei_test()
        : m_mctp(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, ""), m_ncsi(m_mctp) {
    }

    void TearDown() override {
        dev::set_mctp_request_handler(nullptr);
    }

    template <typename T>
    static std::string to_binary_string(const T& value) {
        return std::string(reinterpret_cast<const char*>(&value), sizeof(T));
    }

    template <typename T>
    static std::string to_sized_string(const T& value, size_t length) {
        return std::string(reinterpret_cast<const char*>(&value), length);
    }

    dev::mctp                  m_mctp;
    dev::ncsi_over_mctp_huawei m_ncsi;
};

TEST(ncsi_over_mctp_standard_utils, get_ncsi_command_ctx_sets_expected_fields) {
    auto ctx = dev::get_ncsi_command_ctx(0x01, 0x02, GET_LINK_STATUS, GET_LINK_STATUS_RSP);
    ASSERT_FALSE(ctx.empty());
    EXPECT_EQ(ctx.at("PackageId").as<int64_t>(), 0x01);
    EXPECT_EQ(ctx.at("ChannelId").as<int64_t>(), 0x02);
    EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), GET_LINK_STATUS);
    EXPECT_EQ(ctx.at("ExpectRspPacketType").as<int64_t>(), GET_LINK_STATUS_RSP);
}

TEST(ncsi_over_mctp_standard_utils, convert_speed_mbps_maps_known_values) {
    EXPECT_EQ(dev::convert_speed_mbps(1), 10U);
    EXPECT_EQ(dev::convert_speed_mbps(8), 10000U);
    EXPECT_EQ(dev::convert_speed_mbps(14), 2500U);
    EXPECT_EQ(dev::convert_speed_mbps(0), 0U);
    EXPECT_EQ(dev::convert_speed_mbps(20), 0U);
}

TEST(ncsi_over_mctp_standard_utils, convert_full_duplex_translates_flags) {
    EXPECT_FALSE(dev::convert_full_duplex(0));
    EXPECT_TRUE(dev::convert_full_duplex(1));
    EXPECT_TRUE(dev::convert_full_duplex(8));
    EXPECT_FALSE(dev::convert_full_duplex(15));
    EXPECT_FALSE(dev::convert_full_duplex(32)); // 越界输入视为false
}

TEST(ncsi_over_mctp_standard_utils, convert_link_status_distinguishes_states) {
    EXPECT_EQ(dev::convert_link_status(0x00), 0U);
    EXPECT_EQ(dev::convert_link_status(0x01), 1U);
    EXPECT_EQ(dev::convert_link_status(0xFF), 255U);
}

TEST(ncsi_over_mctp_huawei_utils, get_oem_command_ctx_sets_expected_fields) {
    auto ctx = dev::get_oem_command_ctx(0x03, 0x04);
    ASSERT_FALSE(ctx.empty());
    EXPECT_EQ(ctx.at("PackageId").as<int64_t>(), 0x03);
    EXPECT_EQ(ctx.at("ChannelId").as<int64_t>(), 0x04);
    EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), OEM_COMMAND);
    EXPECT_EQ(ctx.at("ExpectRspPacketType").as<int64_t>(), OEM_COMMAND_RSP);
}

TEST(ncsi_over_mctp_huawei_utils, check_respense_data_accepts_valid_payload) {
    oem_huawei_public_rsp_t rsp{};
    rsp.response_code   = mc::hton(static_cast<uint16_t>(0));
    rsp.reason_code     = mc::hton(static_cast<uint16_t>(0));
    rsp.manufacturer_id = HUAWEI_MANUFACTURE_ID;
    rsp.sub_command_id  = OEM_HUAWEI_GET_BDF;

    EXPECT_TRUE(dev::check_respense_data(&rsp, OEM_HUAWEI_GET_BDF));
}

TEST(ncsi_over_mctp_huawei_utils, check_respense_data_rejects_error_reason) {
    oem_huawei_public_rsp_t rsp{};
    rsp.response_code   = mc::hton(static_cast<uint16_t>(0x0001));
    rsp.reason_code     = mc::hton(static_cast<uint16_t>(0x8002));
    rsp.manufacturer_id = HUAWEI_MANUFACTURE_ID;
    rsp.sub_command_id  = OEM_HUAWEI_GET_BDF;

    EXPECT_FALSE(dev::check_respense_data(&rsp, OEM_HUAWEI_GET_BDF));
}

TEST(ncsi_over_mctp_huawei_utils, check_respense_data_rejects_wrong_manufacturer) {
    oem_huawei_public_rsp_t rsp{};
    rsp.response_code   = mc::hton(static_cast<uint16_t>(0));
    rsp.reason_code     = mc::hton(static_cast<uint16_t>(0));
    rsp.manufacturer_id = 0;
    rsp.sub_command_id  = OEM_HUAWEI_GET_BDF;

    EXPECT_FALSE(dev::check_respense_data(&rsp, OEM_HUAWEI_GET_BDF));
}

TEST(ncsi_over_mctp_huawei_utils, check_respense_data_rejects_wrong_subcommand) {
    oem_huawei_public_rsp_t rsp{};
    rsp.response_code   = mc::hton(static_cast<uint16_t>(0));
    rsp.reason_code     = mc::hton(static_cast<uint16_t>(0));
    rsp.manufacturer_id = HUAWEI_MANUFACTURE_ID;
    rsp.sub_command_id  = OEM_HUAWEI_GET_MAC_ADDR;

    EXPECT_FALSE(dev::check_respense_data(&rsp, OEM_HUAWEI_GET_BDF));
}

TEST(ncsi_over_mctp_huawei_utils, link_width_string_mapping) {
    EXPECT_EQ(dev::get_link_width_str(0x01), "x1");
    EXPECT_EQ(dev::get_link_width_str(0x08), "x8");
    EXPECT_EQ(dev::get_link_width_str(0xFF), "invalid");
    EXPECT_TRUE(dev::get_link_width_str(0x33).empty());
}

TEST(ncsi_over_mctp_huawei_utils, link_speed_string_mapping) {
    EXPECT_EQ(dev::get_link_speed_str(0x01), "Gen1 (2.5GT/s)");
    EXPECT_EQ(dev::get_link_speed_str(0x05), "Gen5 (32GT/s)");
    EXPECT_EQ(dev::get_link_speed_str(0x10), "invalid");
}

TEST(ncsi_over_mctp_huawei_utils, medium_type_string_mapping) {
    EXPECT_EQ(dev::get_medium_type_str(0), "Unknown");
    EXPECT_EQ(dev::get_medium_type_str(1), "Optical");
    EXPECT_EQ(dev::get_medium_type_str(2), "Electric");
    EXPECT_EQ(dev::get_medium_type_str(6), "Baset");
    EXPECT_EQ(dev::get_medium_type_str(30), "Unknown");
}

TEST(ncsi_over_mctp_huawei_utils, connector_type_string_mapping) {
    EXPECT_EQ(dev::get_connector_type_str(0x07), "LC");
    EXPECT_EQ(dev::get_connector_type_str(0x23), "NO_SEPARABLE_CONNECTOR");
    EXPECT_TRUE(dev::get_connector_type_str(0x55).empty());
}

TEST(ncsi_over_mctp_huawei_utils, identifier_string_mapping) {
    EXPECT_EQ(dev::get_identifier_str(0x03), "SFP_SFP_PLUS_SFP28");
    EXPECT_EQ(dev::get_identifier_str(0x11), "QSFP28");
    EXPECT_TRUE(dev::get_identifier_str(0xFE).empty());
}

TEST(ncsi_over_mctp_huawei_utils, covert_micro_to_milli_handles_scaling_and_sentinel) {
    EXPECT_FLOAT_EQ(dev::covert_micro_to_milli(5000), 5.0F);
    EXPECT_FLOAT_EQ(dev::covert_micro_to_milli(3300), 3.3F);
    EXPECT_FLOAT_EQ(dev::covert_micro_to_milli(0xFFFF), static_cast<float>(0xFFFF));
}

TEST_F(ncsi_over_mctp_huawei_test, get_bdf_success) {
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>&,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), OEM_COMMAND);
        oem_huawei_bdf_info_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_BDF;
        response.bus                               = 1;
        response.device                            = 2;
        response.function                          = 3;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_BDF_INFO_RSP_LEN);
        return true;
    });

    dev::ncsi_bdf_info_t info{};
    EXPECT_TRUE(m_ncsi.get_bdf(0, 0, &info));
    EXPECT_EQ(info.bus, 1U);
    EXPECT_EQ(info.device, 2U);
    EXPECT_EQ(info.function, 3U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_bdf_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    dev::ncsi_bdf_info_t info{};
    EXPECT_FALSE(m_ncsi.get_bdf(0, 0, &info));
}

TEST_F(ncsi_over_mctp_huawei_test, get_bdf_invalid_payload) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        rsp.assign(4, '\0');
        return true;
    });
    dev::ncsi_bdf_info_t info{};
    EXPECT_FALSE(m_ncsi.get_bdf(0, 0, &info));
}

TEST_F(ncsi_over_mctp_huawei_test, get_chip_temp_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_temperature_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_CHIP_TEMP;
        response.temperature                       = host_to_be16(0x1234);
        rsp                                        = to_sized_string(response, OEM_HUAWEI_CHIP_TEMP_RSP_LEN);
        return true;
    });
    uint16_t value = 0;
    EXPECT_TRUE(m_ncsi.get_chip_temp(0, 0, &value));
    EXPECT_EQ(value, 0x1234U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_chip_temp_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    uint16_t value = 0;
    EXPECT_FALSE(m_ncsi.get_chip_temp(0, 0, &value));
}

TEST_F(ncsi_over_mctp_huawei_test, get_chip_temp_invalid_size) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        rsp.assign(6, '\0');
        return true;
    });
    uint16_t value = 0;
    EXPECT_FALSE(m_ncsi.get_chip_temp(0, 0, &value));
}

TEST_F(ncsi_over_mctp_huawei_test, get_chip_temp_handles_special_flags) {
    for (uint16_t raw : {uint16_t{0x7FFD}, uint16_t{0x7FFE}, uint16_t{0x7FFF}}) {
        dev::set_mctp_request_handler(
            [raw](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
                oem_huawei_temperature_rsp_t response{};
                response.public_rsp_header.response_code   = host_to_be16(0);
                response.public_rsp_header.reason_code     = host_to_be16(0);
                response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
                response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_CHIP_TEMP;
                response.temperature                       = host_to_be16(raw);
                rsp                                        = to_sized_string(response, OEM_HUAWEI_CHIP_TEMP_RSP_LEN);
                return true;
            });
        uint16_t value = 0;
        EXPECT_TRUE(m_ncsi.get_chip_temp(0, 0, &value));
        EXPECT_EQ(value, raw);
    }
}

TEST_F(ncsi_over_mctp_huawei_test, get_om_temp_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_temperature_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_OM_TEMP;
        response.temperature                       = host_to_be16(0x0405);
        rsp                                        = to_sized_string(response, OEM_HUAWEI_CHIP_TEMP_RSP_LEN);
        return true;
    });
    uint16_t value = 0;
    EXPECT_TRUE(m_ncsi.get_om_temp(0, 0, &value));
    EXPECT_EQ(value, 0x0405U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_om_temp_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    uint16_t value = 0;
    EXPECT_FALSE(m_ncsi.get_om_temp(0, 0, &value));
}

TEST_F(ncsi_over_mctp_huawei_test, get_om_temp_invalid_size) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        rsp.assign(6, '\0');
        return true;
    });
    uint16_t value = 0;
    EXPECT_FALSE(m_ncsi.get_om_temp(0, 0, &value));
}

TEST_F(ncsi_over_mctp_huawei_test, get_om_temp_special_flags) {
    std::array<uint16_t, 3> flags = {0x7FFD, 0x7FFE, 0x7FFF};
    for (auto raw : flags) {
        dev::set_mctp_request_handler(
            [raw](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
                oem_huawei_temperature_rsp_t response{};
                response.public_rsp_header.response_code   = host_to_be16(0);
                response.public_rsp_header.reason_code     = host_to_be16(0);
                response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
                response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_OM_TEMP;
                response.temperature                       = host_to_be16(raw);
                rsp                                        = to_sized_string(response, OEM_HUAWEI_CHIP_TEMP_RSP_LEN);
                return true;
            });
        uint16_t value = 0;
        EXPECT_FALSE(m_ncsi.get_om_temp(0, 0, &value));
    }
}

TEST_F(ncsi_over_mctp_huawei_test, get_dcbx_status_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_dcbx_status_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_DCBX_STATUS;
        for (size_t i = 0; i < MCTP_NCSI_DCBX_FIELD_LEN; ++i) {
            response.cos2_up[i] = static_cast<uint8_t>(i);
            response.up_pgid[i] = static_cast<uint8_t>(i + 1);
            response.pgpct[i]   = static_cast<uint8_t>(i + 2);
            response.strict[i]  = static_cast<uint8_t>(i + 3);
        }
        response.pfcmap = 0xAA;
        rsp             = to_sized_string(response, OEM_HUAWEI_DCBX_STATUS_RSP_LEN);
        return true;
    });

    dev::ncsi_dcbx_status_t status{};
    EXPECT_TRUE(m_ncsi.get_dcbx_status(0, 0, &status));
    EXPECT_EQ(status.pfcmap, 0xAAU);
    EXPECT_EQ(status.cos2_up[0], 0U);
    EXPECT_EQ(status.up_pgid[3], 4U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_dcbx_status_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    dev::ncsi_dcbx_status_t status{};
    EXPECT_FALSE(m_ncsi.get_dcbx_status(0, 0, &status));
}

TEST_F(ncsi_over_mctp_huawei_test, get_link_ability_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_link_ability_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_LINK_ABILITY;
        response.link_width                        = 0x08;
        response.link_speed                        = 0x04;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_LINK_ABILITY_RSP_LEN);
        return true;
    });
    dev::ncsi_link_ability_t ability{};
    EXPECT_TRUE(m_ncsi.get_link_ability(0, 0, &ability));
    EXPECT_EQ(ability.link_width, "x8");
    EXPECT_EQ(ability.link_speed, "Gen4 (16GT/s)");
}

TEST_F(ncsi_over_mctp_huawei_test, get_link_info_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_link_info_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_LINK_INFO;
        response.link_width                        = 0x01;
        response.link_speed                        = 0x05;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_LINK_INFO_RSP_LEN);
        return true;
    });

    dev::ncsi_link_info_t info{};
    EXPECT_TRUE(m_ncsi.get_link_info(0, 0, &info));
    EXPECT_EQ(info.link_width, "x1");
    EXPECT_EQ(info.link_speed, "Gen5 (32GT/s)");
}

TEST_F(ncsi_over_mctp_huawei_test, get_mac_addr_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_mac_addr_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_MAC_ADDR;
        response.mac_addr_count                    = 1;
        std::array<uint8_t, 6> mac = {0, 1, 2, 3, 4, 5};
        std::copy(mac.begin(), mac.end(), response.mac_addr[0]);
        std::array<uint8_t, OEM_HUAWEI_MAC_ADDR_RSP_LEN> raw{};
        std::memcpy(raw.data(), &response, OEM_HUAWEI_MAC_ADDR_RSP_LEN);
        EXPECT_EQ(raw.size(), static_cast<size_t>(OEM_HUAWEI_MAC_ADDR_RSP_LEN));
        rsp.assign(reinterpret_cast<const char*>(raw.data()), raw.size());
        return true;
    });
    uint8_t mac[6] = {};
    EXPECT_TRUE(m_ncsi.get_mac_addr(0, 0, mac, sizeof(mac)));
    EXPECT_EQ(mac[5], 5U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_mac_addr_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    uint8_t mac[6] = {};
    EXPECT_FALSE(m_ncsi.get_mac_addr(0, 0, mac, sizeof(mac)));
}

TEST_F(ncsi_over_mctp_huawei_test, get_default_mac_addr_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_mac_addr_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_DEFAULT_MAC_ADDR;
        response.mac_addr_count                    = 1;
        std::array<uint8_t, 6> mac = {6, 5, 4, 3, 2, 1};
        std::copy(mac.begin(), mac.end(), response.mac_addr[0]);
        std::array<uint8_t, OEM_HUAWEI_MAC_ADDR_RSP_LEN> raw{};
        std::memcpy(raw.data(), &response, OEM_HUAWEI_MAC_ADDR_RSP_LEN);
        EXPECT_EQ(raw.size(), static_cast<size_t>(OEM_HUAWEI_MAC_ADDR_RSP_LEN));
        rsp.assign(reinterpret_cast<const char*>(raw.data()), raw.size());
        return true;
    });
    uint8_t mac[6] = {};
    EXPECT_TRUE(m_ncsi.get_default_mac_addr(0, 0, mac, sizeof(mac)));
    EXPECT_EQ(mac[0], 6U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_fault_state_code_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_fault_state_code_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_FAULT_STATE_CODE;
        response.health_state                      = 1;
        response.error_count                       = 2;
        response.error_code[0]                     = host_to_be16(0x1111);
        response.error_code[1]                     = host_to_be16(0x2222);
        rsp                                        = to_sized_string(response, OEM_HUAWEI_FAULT_STATE_CODE_RSP_LEN);
        return true;
    });

    dev::ncsi_fault_state_code_t code{};
    EXPECT_TRUE(m_ncsi.get_fault_state_code(0, 0, &code));
    EXPECT_EQ(code.health_state, 1U);
    EXPECT_EQ(code.error_count, 2U);
    EXPECT_EQ(code.error_code[1], 0x2222U);
}

TEST_F(ncsi_over_mctp_huawei_test, enable_lldp_capability_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_capability_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_CAPABILITY;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_CAPABILITY_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.enable_lldp_capability(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, disable_lldp_capability_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_capability_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_CAPABILITY;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_CAPABILITY_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.disable_lldp_capability(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, get_lldp_capability_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_get_lldp_capability_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_LLDP_CAPABILITY;
        response.lldp_capability                   = 0x42;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_GET_LLDP_CAPABILITY_RSP_LEN);
        return true;
    });
    uint8_t cap = 0;
    EXPECT_TRUE(m_ncsi.get_lldp_capability(0, 0, &cap));
    EXPECT_EQ(cap, 0x42);
}

TEST_F(ncsi_over_mctp_huawei_test, get_lldp_capability_null_pointer) {
    EXPECT_FALSE(m_ncsi.get_lldp_capability(0, 0, nullptr));
}

TEST_F(ncsi_over_mctp_huawei_test, enable_lldp_tx_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_tx_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_TX;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_TX_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.enable_lldp_tx(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, enable_lldp_tx_request_failure) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string&) {
        return false;
    });
    EXPECT_FALSE(m_ncsi.enable_lldp_tx(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, enable_lldp_tx_old_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_tx_old_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_TX_OLD;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_TX_OLD_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.enable_lldp_tx_old(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, disable_lldp_tx_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_tx_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_TX;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_TX_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.disable_lldp_tx(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, disable_lldp_tx_old_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_enable_lldp_tx_old_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_ENABLE_LLDP_TX_OLD;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_ENABLE_LLDP_TX_OLD_RSP_LEN);
        return true;
    });
    EXPECT_TRUE(m_ncsi.disable_lldp_tx_old(0, 0));
}

TEST_F(ncsi_over_mctp_huawei_test, get_lldp_tx_enable_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_get_lldp_tx_enable_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_LLDP_TX_ENABLE;
        response.lldp_tx_enable                    = 1;
        rsp                                        = to_sized_string(response, OEM_HUAWEI_GET_LLDP_TX_ENABLE_RSP_LEN);
        return true;
    });
    uint8_t enable = 0;
    EXPECT_TRUE(m_ncsi.get_lldp_tx_enable(0, 0, &enable));
    EXPECT_EQ(enable, 1U);
}

TEST_F(ncsi_over_mctp_huawei_test, get_lldp_tx_enable_null_pointer) {
    EXPECT_FALSE(m_ncsi.get_lldp_tx_enable(0, 0, nullptr));
}

TEST_F(ncsi_over_mctp_huawei_test, get_optical_module_info_success) {
    dev::set_mctp_request_handler([](const mc::dict&, const std::vector<uint8_t>&, std::string& rsp) {
        oem_huawei_optical_module_info_rsp_t response{};
        response.public_rsp_header.response_code   = host_to_be16(0);
        response.public_rsp_header.reason_code     = host_to_be16(0);
        response.public_rsp_header.manufacturer_id = HUAWEI_MANUFACTURE_ID;
        response.public_rsp_header.sub_command_id  = OEM_HUAWEI_GET_OPTICAL_MODULE_INFO;
        std::array<uint8_t, MCTP_NCSI_OPTICAL_MODULE_FIELD_LEN> part = {'A', 'B', 'C'};
        std::copy(part.begin(), part.end(), response.part_number);
        response.type                = 1;   // Optical
        response.connector           = 0x07;
        response.transceiver_distance= host_to_be16(100);
        response.wave_length         = host_to_be16(850);
        response.working_voltage     = host_to_be16(3300);
        response.working_tx_bias     = host_to_be16(5000);
        response.working_tx_power    = host_to_be16(6000);
        response.working_rx_power    = host_to_be16(7000);
        response.alarm_tx_power_threshold = host_to_be16(8000);
        response.alarm_rx_power_threshold = host_to_be16(9000);
        response.alarm_low_temp_threshold = host_to_be16(10);
        response.alarm_high_temp_threshold= host_to_be16(90);
        response.rx_los_state        = 1;
        response.tx_full_state       = 0;
        rsp                          = to_sized_string(response, OEM_HUAWEI_OPTICAL_MODULE_INFO_RSP_LEN);
        return true;
    });

    dev::ncsi_optical_module_info_t info{};
    EXPECT_TRUE(m_ncsi.get_optical_module_info(0, 0, &info));
    EXPECT_EQ(info.medium_type, "Optical");
    EXPECT_EQ(info.connector_type, "LC");
    EXPECT_EQ(info.wave_length_nanometer, "850nm");
    EXPECT_TRUE(info.rx_loss_status);
    EXPECT_FALSE(info.tx_fault_status);
}

} // namespace

